"""
# new Env("github-gitee仓库监控")
# cron: 0 0 0 2/10 * ? 
代码功能：监控指定代码仓库的文件变动情况，并通过PushPlus发送HTML格式的变动报告
主要特性：
1. 支持GitHub和Gitee平台
2. 自动获取默认分支
3. 分析24小时内的提交记录
4. 分类统计新增/删除/修改的文件
5. 生成美观的HTML报告
# 仓库列表，Z_script_LIST  格式：仓库名#仓库URL    //多仓库换行
# API令牌，Z_TOKEN_LIST  格式：github:token;gitee:token    //完整粘贴更换token
# PushPlus通知令牌  PUSH_PLUS_TOKEN
# PushPlus用户ID  PUSH_PLUS_USER
"""
import os
import requests
from datetime import datetime, timedelta
import pytz

# 环境变量配置
Z_script_LIST = os.environ.get("Z_script_LIST", "")
Z_TOKEN_LIST = os.environ.get("Z_TOKEN_LIST", "")
PUSH_PLUS_TOKEN = os.environ.get("PUSH_PLUS_TOKEN", "")
PUSH_PLUS_USER = os.environ.get("PUSH_PLUS_USER", "")

# 解析令牌
TOKENS = {}
if Z_TOKEN_LIST:
    for token_pair in Z_TOKEN_LIST.split(";"):
        if ":" in token_pair:
            platform, token = token_pair.split(":", 1)
            TOKENS[platform.strip().lower()] = token.strip()

# 样式配置
COLORS = ["#4A90E2", "#50B674"]
CSS_STYLE = """
<style>
  .repo-title { color: #2c3e50; margin-bottom: 8px; }
  .time-range { color: #7f8c8d; font-size: 0.9em; }
  ul { 
    padding-left: 1.2em;
    line-height: 1.6;
    list-style-type: none;
    margin: 0.5em 0;
  }
  li { 
    margin: 0.3em 0;
    font-family: 'Consolas', monospace;
    word-break: break-all;
  }
  hr {
    margin: 1.2em 0;
    border: 0;
    border-top: 1px solid #ecf0f1;
  }
</style>
"""

def parse_repo_url(url):
    """解析仓库URL返回平台、owner和repo名称"""
    url = url.strip().rstrip('/')
    if 'github.com' in url:
        parts = url.split('/')
        platform = 'github'
    elif 'gitee.com' in url:
        parts = url.split('/')
        platform = 'gitee'
    else:
        return None, None, None
    
    if len(parts) < 5:
        return None, None, None
    
    owner = parts[-2]
    repo = parts[-1].replace('.git', '')
    return platform, owner, repo

def get_default_branch(platform, owner, repo):
    """获取仓库默认分支（带错误处理）"""
    try:
        if platform == 'github':
            url = f'https://api.github.com/repos/{owner}/{repo}'
            headers = {'Authorization': f'Bearer {TOKENS.get("github", "")}'}
            response = requests.get(url, headers=headers, timeout=10)
            return response.json().get('default_branch', 'main')
        elif platform == 'gitee':
            url = f'https://gitee.com/api/v5/repos/{owner}/{repo}'
            params = {'access_token': TOKENS.get("gitee", "")}
            response = requests.get(url, params=params, timeout=10)
            return response.json().get('default_branch', 'master')
    except Exception as e:
        print(f"获取默认分支失败：{str(e)}")
        return 'main' if platform == 'github' else 'master'

def get_commits(platform, owner, repo, branch, start_time, end_time):
    """获取时间范围内的提交记录"""
    tz = pytz.timezone('Asia/Shanghai')
    start_iso = start_time.astimezone(tz).isoformat()
    end_iso = end_time.astimezone(tz).isoformat()
    
    commits = []
    page = 1
    while True:
        try:
            if platform == 'github':
                url = f'https://api.github.com/repos/{owner}/{repo}/commits'
                headers = {'Authorization': f'Bearer {TOKENS.get("github", "")}'}
                params = {
                    'sha': branch,
                    'since': start_iso,
                    'until': end_iso,
                    'per_page': 100,
                    'page': page
                }
                response = requests.get(url, headers=headers, params=params, timeout=15)
            else:
                url = f'https://gitee.com/api/v5/repos/{owner}/{repo}/commits'
                params = {
                    'access_token': TOKENS.get("gitee", ""),
                    'sha': branch,
                    'since': start_iso,
                    'until': end_iso,
                    'page': page,
                    'per_page': 100
                }
                response = requests.get(url, params=params, timeout=15)
            
            if response.status_code != 200:
                print(f"API请求失败：{response.status_code} - {response.text[:200]}")
                break
            
            data = response.json()
            if not data:
                break
                
            commits.extend(data)
            page += 1
        except Exception as e:
            print(f"获取提交记录异常：{str(e)}")
            break
    return commits

def analyze_commits(platform, owner, repo, commits):
    """分析提交记录获取文件变动"""
    added = set()
    removed = set()
    modified = set()
    
    for commit in commits:
        try:
            sha = commit['sha']
            
            if platform == 'github':
                url = f'https://api.github.com/repos/{owner}/{repo}/commits/{sha}'
                headers = {'Authorization': f'Bearer {TOKENS.get("github", "")}'}
                response = requests.get(url, headers=headers, timeout=10)
            else:
                url = f'https://gitee.com/api/v5/repos/{owner}/{repo}/commits/{sha}'
                params = {'access_token': TOKENS.get("gitee", "")}
                response = requests.get(url, params=params, timeout=10)
            
            if response.status_code != 200:
                continue
                
            files = response.json().get('files', [])
            for file in files:
                status = file.get('status', '').lower()
                filename = file.get('filename', '')
                
                status_map = {
                    'renamed': 'renamed',
                    'added': 'added',
                    'removed': 'removed',
                    'modified': 'modified',
                    'changed': 'modified'
                }
                status = status_map.get(status, status)
                
                if status == 'renamed':
                    removed.add(file.get('previous_filename', ''))
                    added.add(filename)
                elif status == 'added':
                    added.add(filename)
                elif status == 'removed':
                    removed.add(filename)
                elif status == 'modified':
                    modified.add(filename)
        except Exception as e:
            print(f"文件分析异常：{str(e)}")
            continue
            
    return added, removed, modified

def generate_section(title, items):
    """生成带颜色交替的HTML内容块"""
    if not items:
        return ""
    
    lines = []
    for i, item in enumerate(sorted(items)):
        color = COLORS[i % 2]
        lines.append(f'<li><font color="{color}">{item}</font></li>')
    
    return f"""
<div class="section">
  <strong>{title}</strong>
  <ul>{"".join(lines)}</ul>
</div>
"""

def send_pushplus_notification(title, content):
    """发送HTML格式的PushPlus通知"""
    full_content = f"{CSS_STYLE}<div class='container'>{content}</div>"
    data = {
        "token": PUSH_PLUS_TOKEN,
        "user": PUSH_PLUS_USER,
        "title": title,
        "content": full_content,
        "template": "html"
    }
    try:
        response = requests.post('https://www.pushplus.plus/send', json=data, timeout=10)
        return response.status_code == 200
    except Exception as e:
        print(f"通知发送失败：{str(e)}")
        return False

def main():
    if not Z_script_LIST.strip():
        print("⚠️ Z_script_LIST环境变量未配置，程序终止")
        return
    
    if not TOKENS:
        print("⚠️ Z_TOKEN_LIST环境变量未配置或格式错误，程序终止")
        return

    tz = pytz.timezone('Asia/Shanghai')
    end_time = datetime.now(tz)
    start_time = end_time - timedelta(hours=24)
    
    all_content = []
    total_changes = 0

    print(f"开始检测时间范围：{start_time.strftime('%Y-%m-%d %H:%M')} 至 {end_time.strftime('%Y-%m-%d %H:%M')}")
    
    for line in Z_script_LIST.split('\n'):
        if not line.strip() or '#' not in line:
            continue
            
        try:
            repo_name, repo_url = line.split('#', 1)
            platform, owner, repo = parse_repo_url(repo_url)
            if not platform:
                print(f"⚠️ 仓库解析失败：{repo_url}")
                continue
                
            print(f"\n🔍 正在处理：{repo_name} ({platform.upper()})")
            
            branch = get_default_branch(platform, owner, repo)
            print(f"  默认分支：{branch}")
            
            commits = get_commits(platform, owner, repo, branch, start_time, end_time)
            if not commits:
                print("  无新提交记录")
                continue
            print(f"  获取到 {len(commits)} 条提交")
            
            added, removed, modified = analyze_commits(platform, owner, repo, commits)
            if not any([added, removed, modified]):
                print("  无有效文件变动")
                continue
                
            time_range = f"{start_time.strftime('%Y-%m-%d %H:%M')} 至 {end_time.strftime('%Y-%m-%d %H:%M')}"
            content = f"""
<div class="repo-block">
  <h3 class="repo-title">📦 仓库 {repo_name}</h3>
  <div class="meta-info">
    <span>平台：{platform.upper()}</span>
    <span class="time-range">检测时间：{time_range}</span>
  </div>
  {generate_section("新增文件", added)}
  {generate_section("删除文件", removed)}
  {generate_section("修改文件", modified)}
</div>
<hr>
"""
            all_content.append(content)
            total_changes += 1
            
        except Exception as e:
            print(f"处理仓库异常：{str(e)}")
            continue

    if total_changes > 0:
        title = f"🏷️ 仓库变动报告（共 {total_changes} 个仓库）"
        final_content = "".join(all_content)
        if send_pushplus_notification(title, final_content):
            print("\n✅ 通知发送成功")
        else:
            print("\n❌ 通知发送失败")
    else:
        print("\nℹ️ 所有仓库无变动，不发送通知")

if __name__ == '__main__':
    main()